import * as echarts from 'echarts/core'
import { shallowRef, shallowReactive, useAttrs, onBeforeUnmount } from 'vue'
// 引入提示框，标题，直角坐标系，数据集，内置数据转换器组件，组件后缀都为 Component
import { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, LegendComponent, ToolboxComponent } from 'echarts/components'
// 引入折线图，柱状图，饼图，散点图组件，组件后缀都为 Chart
import { BarChart, LineChart, PieChart, GaugeChart, MapChart } from 'echarts/charts'
// 标签自动布局、全局过渡动画等特性
import { LabelLayout, UniversalTransition } from 'echarts/features'
// 引入 Canvas 渲染器，注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'

const optionsModules = import.meta.glob('./options/*.js', { eager: true })

/**
 *  视口变化时echart图表自适应调整
 */
class ChartsResize {
  #charts = new Set()
  #timeId = null

  constructor () {
    window.addEventListener('resize', this.handleResize.bind(this))
  }
  getCharts () {
    return [...this.#charts]
  }
  handleResize () {
    clearTimeout(this.#timeId)
    this.#timeId = setTimeout(() => {
      this.#charts.forEach((chart) => {
        chart.resize()
      })
    }, 500)
  }
  add (chart) {
    this.#charts.add(chart)
  }
  remove (chart) {
    chart.dispose()
    this.#charts.delete(chart)
  }

  removeListener () {
    window.removeEventListener('resize', this.handleResize)
  }
}

export const chartsResize = new ChartsResize()

export const useCharts = ({ type, el, mapData }) => {
  echarts.use([BarChart, LineChart, PieChart, GaugeChart, MapChart, TitleComponent, TooltipComponent, ToolboxComponent, GridComponent, DatasetComponent, TransformComponent, LabelLayout, UniversalTransition, CanvasRenderer, SVGRenderer, LegendComponent])

  const charts = shallowRef(null)
  let options
  const getOptions = async () => {
    const moduleKey = `./options/${type.value}.js`
    const { default: defaultOption } = await optionsModules[moduleKey]
    return defaultOption
  }

  const setOptions = (opt) => {
    charts.value.setOption(opt)
  }

  const initChart = async () => {
    charts.value = echarts.init(el.value, null, { renderer: 'svg' })
    charts.value.clear()
    options = await getOptions()
    if (type.value === 'map' && mapData.value) {
      echarts.registerMap('yinzhou', mapData.value)
    }
    charts.value.setOption(options)
    chartsResize.add(charts.value)
    // 添加事件支持
    initEvent()
  }

  /**
   * 初始化事件,按需绑定事件
   */
  const attrs = useAttrs()
  const initEvent = () => {
    Object.keys(attrs).forEach((attrKey) => {
      if (/^on/.test(attrKey)) {
        const originCb = attrs[attrKey]
        attrKey = attrKey.replace(/^on(Chart)?/, '')
        attrKey = `${attrKey[0].toLocaleLowerCase()}${attrKey.substring(1)}`
        if (typeof originCb === 'function') {
          const cb = (...args) => {
            originCb(...args, charts.value)
          }
          charts.value?.on(attrKey, cb)
        }
      }
    })
  }

  onBeforeUnmount(() => {
    // 移除缓存
    chartsResize.remove(charts.value)
  })

  return {
    charts,
    setOptions,
    initChart,
    initEvent
  }
}

export const chartsOptions = (option) => shallowReactive(option)
